import { Button, Checkbox, Flex, Form, Input, Modal, Space, Spin, Table, Tree, Typography, message } from "antd";
import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef } from "react";
import styled from "styled-components";
import { useState } from "react";
import * as sqlFormatter from "sql-formatter";
import { keepPreviousData, useQuery } from "@tanstack/react-query";
import { ExclamationCircleFilled, FolderOpenOutlined } from '@ant-design/icons';
import StructureFieldModal from "./StructureFieldModal";
import CodeEditor from "@/components/codemirror/CodeEditor";
import { subjectNodeTreeById, subjectNodeDeleteById, subjectQueryDaMengData, subjectQueryRedisData, subjectNodeSaveQuery } from '@/api/sharing/dataSubject'

const StructureForm = forwardRef(({ style, subjectDetail }, ref) => {
  const [selectedNode, setSelectedNode] = useState({})
  const [formData, setFormData] = useState({
    nodeResult: '',
    nodeText: `SELECT * FROM JCGX_DATA_SOURCE`,
  });

  const structureFieldRef = useRef();


  const { data: treeData, isFetching, refetch } = useQuery({
    queryKey: ['StructureForm-subjectNodeTreeById', subjectDetail.id],
    queryFn: () => {
      return subjectNodeTreeById(subjectDetail.id).then((res) => {
        return res?.result || []
      })
    },
    staleTime: 0,
    placeholderData: keepPreviousData,
  })

  useImperativeHandle(ref, () => ({
    validateFields: validateFields,
    submit: () => {
      // if (!formData.nodeResult) {
      //   return subjectNodeQueryById({ id: selectedNode.id, query: formData.nodeText }).then(({ code, result: nodeResult }) => {
      //     if (code !== 200) return;
      //     let data = ''
      //     if (selectedNode.dataSourceType === 'REDIS') {
      //       data = nodeResult ? nodeResult[0] || '' : ''
      //     } else {
      //       data = JSON.stringify(nodeResult || [])
      //     }
      //     return subjectNodeSaveQuery({ id: selectedNode.id, nodeText: formData.nodeText, data }).then(() => {
      //       refetch()
      //     })
      //   })
      // }
      return subjectNodeSaveQuery({ id: selectedNode.id, nodeText: formData.nodeText, data: formData.nodeResult }).then((res) => {
        refetch()
        return res
      })
    }
  }))



  const validateFields = async () => {
    if (selectedNode.nodeType === 'DATA') {
      if (selectedNode.dataSourceType === 'REDIS' && !formData.nodeText) {
        message.error('请输入Redis缓存Key')
        return Promise.reject('')
      }

      if (selectedNode.dataSourceType !== 'REDIS' && !formData.nodeText) {
        message.error('请输入sql执行语句')
        return Promise.reject('')
      }
    } else {
      return Promise.resolve()
    }
  }

  const onSelect = (selectedKeys, info) => {
    if (selectedNode.id === info.node.id) {
      setSelectedNode({})
      setFormData({})
    } else {
      setSelectedNode(info.node)
      setFormData({ nodeResult: info.node.nodeResult || '', nodeText: info.node.nodeText || '' })
    }
    console.log('selected', selectedKeys, info);
  };

  const deleteConfirm = (row) => {
    Modal.confirm({
      title: '确认删除所选中数据?',
      icon: <ExclamationCircleFilled />,
      autoFocusButton: null,
      onOk() {
        return subjectNodeDeleteById(row.id)
          .then((res) => {
            if (res.code === 200) {
              setSelectedNode({})
              refetch()
              message.success('删除成功')
            }
          })
      },
      onCancel() { },
    });
  };

  const updateFormData = (data) => {
    setFormData({ ...formData, ...data })
  }

  const getIsFixedNode = (node) => {
    return node.id && node.parentId === '-1' && ['id', 'name'].includes(node.nodeName)
  }

  const isFixedNode = useMemo(() => {
    return getIsFixedNode(selectedNode)
  }, [selectedNode])

  return <StyleWrapper style={style}>
    <div className="left-box">
      <Flex justify={'end'}>
        <Space>
          <Button disabled={selectedNode.nodeType === 'DATA' || isFixedNode} type="primary" onClick={() => structureFieldRef.current.showAddModal(selectedNode)}>新增</Button>
          <Button disabled={!selectedNode.id || isFixedNode} type="primary" onClick={() => structureFieldRef.current.showEditModal(selectedNode)}>修改</Button>
          <Button disabled={!selectedNode.id} danger onClick={() => deleteConfirm(selectedNode)}>删除</Button>
        </Space>
      </Flex>
      <Spin spinning={isFetching}>
        <Tree
          defaultExpandAll
          blockNode
          selectedKeys={selectedNode.id && [selectedNode.id]}
          fieldNames={{
            title: 'nodeName',
            key: 'id',
            children: 'childrenList'
          }}
          onSelect={onSelect}
          treeData={treeData}
          titleRender={(node) => {
            return <>
              <Checkbox style={{ "marginLeft": '-8px', marginRight: '8px' }} checked={selectedNode.id === node.id} />{node.nodeType === 'CATALOG' && !getIsFixedNode(node) && <FolderOpenOutlined />} {node.nodeName}
            </>
          }}
        />
      </Spin>
    </div >
    {
      !!selectedNode.id && <div className="right-box">
        {
          (selectedNode.nodeType === 'CATALOG' || isFixedNode) &&
          <div className="simple-view">
            <span>{selectedNode.nodeName}：</span>
            <span>{selectedNode.nodeResult || '数据目录'}</span>
          </div>
        }
        {
          selectedNode.nodeType === 'DATA' && !isFixedNode && selectedNode.dataSourceType === 'DAMENG' &&
          <SqlPreview selectedNode={selectedNode} formData={formData} setFormData={updateFormData} />
        }
        {
          selectedNode.nodeType === 'DATA' && !isFixedNode && selectedNode.dataSourceType === 'REDIS' &&
          <RedisPreview selectedNode={selectedNode} formData={formData} setFormData={updateFormData} />
        }
      </div>
    }

    <StructureFieldModal ref={structureFieldRef} themeId={subjectDetail.id} onFinish={refetch}></StructureFieldModal>
  </StyleWrapper >
})

const SqlPreview = ({ selectedNode, setFormData, formData }) => {
  const { nodeResult, nodeText } = formData
  const [loading, setLoading] = useState(false)
  const tableData = useMemo(() => {
    if (!nodeResult) return []
    return JSON.parse(nodeResult)
  }, [nodeResult])

  const columns = useMemo(() => {
    if (!tableData.length) return []
    return Object.keys(tableData[0]).map(key => {
      return {
        title: key,
        dataIndex: key,
        align: 'center',
      }
    })
  }, [tableData])

  const handleQuery = () => {
    if (!nodeText) return message.error('请输入查询语句')
    setLoading(true)
    subjectQueryDaMengData({ id: selectedNode.id, query: nodeText }).then((res) => {
      setFormData({ nodeResult: JSON.stringify(res?.result || []) })
      setLoading(false)
    })
  }

  return <div>
    <div style={{ marginBottom: 20 }}>
      <CodeEditor value={nodeText} onChange={(val) => {
        setFormData({ nodeText: val })
      }} height={'200px'} lang="sql" />
    </div>
    <Flex justify={'space-between'} align={'center'}>
      <Typography.Title level={5} style={{ marginBottom: 0 }}>结果预览</Typography.Title>
      <Space>
        <Button type="primary" onClick={handleQuery}>查询</Button>
        <Button type="primary" onClick={() => { setValue(sqlFormatter.format(value)) }}>美化SQL</Button>
      </Space>
    </Flex>
    <Table rowKey={(record) => record.id} scroll={{ x: 'max-content' }} pagination={false} loading={loading} columns={columns} dataSource={tableData} />
  </div>
}

const RedisPreview = ({ selectedNode, setFormData, formData }) => {
  const { nodeResult, nodeText } = formData
  const [loading, setLoading] = useState(false)

  const jsonStr = useMemo(() => {
    if (!nodeResult) return ""
    return nodeResult
  }, [nodeResult])

  const handleQuery = () => {
    if (!nodeText) return message.error('请输入Redis缓存Key')
    setLoading(true)
    subjectQueryRedisData({ id: selectedNode.id, query: nodeText }).then(({ result }) => {
      setFormData({ nodeResult: result || '' })
      setLoading(false)
    })
  }

  return <div>
    <Flex align="center" style={{ marginBottom: '20px' }}>
      <span style={{ flexShrink: 0 }}>请输入Redis缓存Key：</span>
      <Input value={nodeText} onChange={(e) => {
        setFormData({ nodeText: e.target.value })
      }} style={{ marginRight: '10px' }} placeholder="支持#{key}的方式从输入url中动态获取参数" />
      <Button onClick={handleQuery} type="primary">读取</Button>
    </Flex>
    <Spin spinning={loading}>
      <CodeEditor value={jsonStr} onChange={(val) => {
        setFormData({ nodeResult: val })
      }} height={'300px'} lang="json" readOnly />
    </Spin>
  </div>
}


const StyleWrapper = styled.div`
  display: flex;
  max-width: 1000px;
  margin: 0 auto;
  .left-box{
    border-radius: 2px;
    border: 1px solid #326394;
    background-color: #002146;
    padding: 14px;
    width: 420px;
    .ant-tree{
      margin-top: 20px;
    }
  }
  .right-box{
    margin-left: 20px;
    flex: 1;
    width: 0;
    .ant-table{
      margin-top: 10px;
    }
  }
  .simple-view{
    span:first-child{
      color: #9ccdff;
    }
    span:last-child{
      border: 1px solid #326394;
      background-color: #002146;
      padding: 8px 12px;
      border-radius: 2px;
    }
  }
`

export default StructureForm